import axios from "axios";
import crypto from "crypto";

const WECHAT_APP_ID = process.env.WECHAT_APP_ID;
const WECHAT_APP_SECRET = process.env.WECHAT_APP_SECRET;

/**
 * https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
 * 获取微信开放平台的 access_token，注意这个 access_token 和公众号的通过用户授权 code 获取的 access_token 不一样,这是基础的 access_token
 * access_token 的有效期目前为 2 个小时，需定时刷新，重复获取将导致上次获取的 access_token 失效。
 * 因此需要缓存 access_token，并设置过期时间
 *
 * 正常返回
 * {
 *   "access_token":"ACCESS_TOKEN",
 *   "expires_in":7200
 * }
 *
 * 异常返回
 * {
 *   "errcode":40013,
 *   "errmsg":"invalid appid"
 * }
 * @returns {Promise<string>} 访问令牌
 */

const ACCESS_TOKEN_CACHE = {};
const JS_API_TICKET_CACHE = {};
async function getAccessToken() {
  const now = Date.now();
  const cache = ACCESS_TOKEN_CACHE[WECHAT_APP_ID];
  if (cache && now < cache.expireTime) {
    return cache.accessToken;
  }
  // https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
  const response = await axios.get(
    `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${WECHAT_APP_ID}&secret=${WECHAT_APP_SECRET}`
  );
  const accessToken = response.data.access_token;
  const expiresIn = response.data.expires_in;
  const expireTime = now + expiresIn * 1000;
  ACCESS_TOKEN_CACHE[WECHAT_APP_ID] = { accessToken, expireTime };
  return accessToken;
}

/**
 * 获取微信 JS API 的 ticket
 * https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
 * 有效期7200秒，开发者必须在自己的服务全局缓存jsapi_ticket
 * @returns {Promise<string>} 访问令牌
 */
async function getJsApiTicket() {
  const now = Date.now();
  const cache = JS_API_TICKET_CACHE[WECHAT_APP_ID];
  if (cache && now < cache.expireTime) {
    return cache.jsApiTicket;
  }
  try {
    const accessToken = await getAccessToken();
    console.log("getJsApiTicket", accessToken);
    const response = await axios.get(
      `https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${accessToken}&type=jsapi`
    );
    const jsApiTicket = response.data.ticket;
    const expiresIn = response.data.expires_in;
    const expireTime = now + expiresIn * 1000;
    JS_API_TICKET_CACHE[WECHAT_APP_ID] = { jsApiTicket, expireTime };
    return jsApiTicket;
  } catch (error) {
    console.error("获取 jsApiTicket 失败:", error);
    if (
      error.response.data.errcode === 40164 ||
      error.response.data.errcode === 40001
    ) {
      delete ACCESS_TOKEN_CACHE[WECHAT_APP_ID];
      return await getJsApiTicket();
    }
    throw error;
  }
}

// 生成签名
function generateSignature(nonceStr, timestamp, url, jsapi_ticket) {
  const queryString = `jsapi_ticket=${jsapi_ticket}&noncestr=${nonceStr}&timestamp=${timestamp}&url=${url}`;
  const sha1 = crypto.createHash("sha1");
  sha1.update(queryString);
  return sha1.digest("hex");
}

// 获取前端需要的配置
export async function wxJsConfig(url) {
  'use server'
  const jsapi_ticket = await getJsApiTicket();
  const nonceStr = Math.random().toString(36).substr(2, 15);
  const timestamp = Math.floor(Date.now() / 1000);
  const signature = generateSignature(nonceStr, timestamp, url, jsapi_ticket);

  console.log("wxJsConfig", {
    appId: WECHAT_APP_ID,
    timestamp,
    nonceStr,
    signature,
  });
  return {
    appId: WECHAT_APP_ID,
    timestamp,
    nonceStr,
    signature,
  };
}

/**
 * 用户微信登录
 * https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
 *
 * return {
  "access_token":"ACCESS_TOKEN",
  "expires_in":7200,
  "refresh_token":"REFRESH_TOKEN",
  "openid":"OPENID",
  "scope":"SCOPE",
  "is_snapshotuser": 1,
  "unionid": "UNIONID"
}
 * @param {string} code
 */
export async function wechatLogin(code) {
  const data = await getUserAccessToken(code);
  const accessToken = data.access_token;
  const refreshToken = data.refresh_token;
  const expiresIn = data.expires_in;
  const openid = data.openid;
  return {
    accessToken,
    refreshToken,
    expiresIn,
    openid,
  };
}

/**
 * 获取用户的 accessToken
 * https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
 * return ok {
  "access_token":"ACCESS_TOKEN",
  "expires_in":7200,
  "refresh_token":"REFRESH_TOKEN",
  "openid":"OPENID",
  "scope":"SCOPE"
}
 */

export async function getUserAccessToken(code) {
  const response = await axios.get(
    `https://api.weixin.qq.com/sns/oauth2/access_token?appid=${WECHAT_APP_ID}&secret=${WECHAT_APP_SECRET}&code=${code}&grant_type=authorization_code`
  );
  return response.data;
}

/**
 * 刷新 accessToken
 * https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
 * return ok {
  "access_token":"ACCESS_TOKEN",
  "expires_in":7200,
  "refresh_token":"REFRESH_TOKEN",
  "openid":"OPENID",
  "scope":"SCOPE"
}
 * return fail { "errcode":40029,"errmsg":"invalid code"}
 */
export async function refreshAccessToken(refreshToken) {
  const response = await axios.get(
    `https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=${WECHAT_APP_ID}&grant_type=refresh_token&refresh_token=${refreshToken}`
  );
  const data = response.data;
  return data;
}

/**
 * 获取用户信息
 * https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
 *
 * return {
  "openid": "OPENID",
  "nickname": NICKNAME,
  "sex": 1,
  "province":"PROVINCE",
  "city":"CITY",
  "country":"COUNTRY",
  "headimgurl":"https://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",
  "privilege":[ "PRIVILEGE1" "PRIVILEGE2"     ],
  "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
 * @param {string} openid
 * @param {string} accessToken
 */
export async function getUserInfo(openid, accessToken) {
  const response = await axios.get(
    `https://api.weixin.qq.com/sns/userinfo?access_token=${accessToken}&openid=${openid}&lang=zh_CN`
  );
  return response.data;
}
